#!/usr/bin/env python2.6
import sys
import warnings
import os

# Well.
# This is a main application script that initializes all subsystems:
# the database, collection manager, GUI; also it parses passed command
# line arguments.

# Extract command line arguments
import optparse

parser = optparse.OptionParser()
parser.add_option("", "--verbose", 
    action="store_true", dest="verbose", default=False,
    help="More verbose output into stderr")

(options, args) = parser.parse_args()

# set old time representation format: integer not float
# see /usr/share/doc/python2.5/html/lib/os-file-dir.html
os.stat_float_times(False)

try:
    import pygtk
    pygtk.require('2.0')
except ImportError:
    print >> sys.stderr, "Unable to find module `pygtk', terminating"
    sys.exit(1)
except AssertionError, e:
    print >> sys.stderr, "GTK initializing error:", e.message
    sys.exit(1)

# Force warnings to be errors to catch  'could not open display' warning
import warnings
warnings.simplefilter("error")

try:
    import gtk
except Warning, msg:
    if str(msg) == 'could not open display':
        print >> sys.stderr, "couldn't open display"
        sys.exit(1)
except ImportError:
    print >> sys.stderr, "couldn't find module `gtk', terminating"
    sys.exit(1)

warnings.resetwarnings()

# since that moment we can display GUI message with an error.
def _local_error(message):
    print >> sys.stderr, message
    dialog = gtk.MessageDialog(None, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR,
        gtk.BUTTONS_OK)
    dialog.format_secondary_text(message)
    dialog.set_title("pybookshelf fatal error")
    dialog.run()
    dialog.destroy()

# Detect is pybookshelf installed or is launched from development directory.
# Looking for file `pybookshelf.glade', assume it doesn't exist when
# application is installed
base_dir = os.path.dirname(os.path.realpath(__file__))
installed = not os.path.exists(os.path.join(base_dir, 'pybookshelf.glade'))

# Initialize subsystems/modules
try:
    import pybs.path as path
    path.initialize(installed)
except ImportError:
    _local_error("couldn't find internal module `path', terminating")
    sys.exit(1)
except:
    _local_error("couldn't find internal module `path', terminating")
    sys.exit(1)

try:
    from pybs import settings
    settings.initialize(path.get_config_path("settings.ini"))
except ImportError:
    _local_error("couldn't find internal module `settings', terminating")
    sys.exit(1)
except BaseException, e:
    _local_error("couldn't initialize internal module `settings': %s" % e)
    sys.exit(1)
    
path.initialize_service_dir()

import gettext
import locale
import gtk.glade

# initialize gettext
gettext.textdomain("pybookshelf")
gettext.bindtextdomain("pybookshelf", path.locale_dir)
# install function _() into top level namespace
gettext.install("pybookshelf", unicode=True, localedir=path.locale_dir)

try:
    import gtk.glade
except ImportError:
    errors = []
    errors.append(_("GTK+ runtime is missing libglade support"))
    if "nt" == os.name:
        errors.append(_("Please remove your current GTK+ runtime and install newer version"))
    else:
        errors.append(_("Please make sure that GTK+ and PyGtk have libglade support"))
        
    _local_error("\n".join(errors))
    sys.exit(1)

gtk.glade.textdomain("pybookshelf")
gtk.glade.bindtextdomain("pybookshelf", path.locale_dir)

# initialize unicode workarounds
import pybs.strunicode as strunicode
strunicode.initialize()

try:
    from pybs import core
except ImportError:
    print >> sys.stderr, "couldn't find internal module `core', terminating"
    sys.exit(1)

# check is pybookshelf is already running
pidfile = path.get_config_path("pid")
try:
    f = open(pidfile)
    pid = f.read()
    try:
        pid = int(pid)
    except ValueError:
        f.close()
        raise Exception()
    
    try:
        os.kill(pid, 0)
        running = True
    except OSError:
        running = False
        
    f.close()
except IOError:
    running = False
except Exception:
    running = False

if running:
    core.error(_("Another instance of pybookshelf is already running!"))
    os.sys.exit(1)
else:
    f = open(pidfile, "w")
    f.write(str(os.getpid()))
    f.close()
    
# initialize logging facility
import pybs.log as log
if options.verbose:
    log.set_logging(level=log.DEBUG)
else:
    log.set_logging(level=log.ERROR)
    
import gobject
gobject.threads_init()

error_flag = False
errors = []

try:
    import gtkmozembed
    # workaround: create empty MozEmbed object to prevent crashes when last MozEmbed() object destroyed
    gtkmozembed.set_profile_path(path.get_cache_path(), "gtkmozemedcache")
    empty_moz = gtkmozembed.MozEmbed()
except ImportError:
    error_flag = True
    errors.append(_("couldn't find module `gtkmozembed'"))
    
if gtk.pygtk_version < (2, 8, 0):
    error_flag = True
    errors.append(_("PyBookshelf needs PyGtk >= 2.8 to run"))
elif gtk.gtk_version < (2, 8, 0):
    error_flag = True
    errors.append(_("PyBookshelf needs Gtk >= 2.8 to run"))

# load plugins
from pybs import plugin
plugin.initialize((os.path.join(path.lib_dir, "plugins"),))

if error_flag:
    core.error("\n".join(errors))
    sys.exit(1)

from pybs import exceptions

# load/connect database
do_init_database = False

# FIXME: move path.get_config_path("collection.db") to the `path' module
db_path = path.get_config_path("collection.db")
if not os.path.isfile(db_path):
    do_init_database = True

from pybs import database
try:
    database.initialize(db_path)
except exceptions.DbError, e:
    msg = _("Unable to connect to the database: %s") % e.message
    log.error(msg)
    core.error(msg)
    sys.exit(1)
    
if do_init_database:
    try:
        # initialize database
        schema_files = ("db-files.sql", "db-bookmarks.sql", "db-metadata.sql", "db-indices.sql", 
            "db-views.sql", "db-rating.sql", "db-settings.sql", "db-shelves.sql")
        for s in schema_files:
            database.import_sql_file(path.get_data_path("sql", s))
    except exceptions.DbError, e:
        msg = _("Unable to initialize the database: %s") % e.message
        log.error(msg)
        core.error(msg)
        sys.exit(1)

# check that database is ok for collection
from pybs import collection
try:
    collection.check_database()
except exceptions.CollectionError, e:
    log.error(e.message)
    core.error(e.message)
    sys.exit(1)

#from pybs.gui.main import Pybookshelf
from pybs.gui import main as main_gui

main_gui.initialize()
main_gui.create_gui()

core.set_main_parent(main_gui.window)

try:
    #import profile
    #profile.run("main()")
    gtk.main()
except SystemExit:
    raise
except:
    import traceback
    traceback.print_exc()

